package com.cencat.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.common.enums.ErrorCode;
import com.cencat.common.exception.BusinessException;
import com.cencat.common.enums.UserStatus;
import com.cencat.common.utils.CryptoUtils;
import com.cencat.common.utils.BeanUtils;
import com.cencat.common.utils.PaginationHelper;
import com.cencat.common.utils.ValidationUtils;
import com.cencat.common.utils.CencatStringUtils;
import com.cencat.common.response.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;
import com.cencat.user.config.CacheConfig;
import com.cencat.user.dto.UserCreateDTO;
import com.cencat.user.dto.UserQueryDTO;
import com.cencat.user.dto.UserUpdateDTO;
import com.cencat.user.dto.LoginDTO;
import com.cencat.user.dto.TokenDTO;
import com.cencat.user.dto.LogoutDTO;
import com.cencat.user.entity.User;
import com.cencat.user.mapper.UserMapper;
import com.cencat.user.service.UserService;
import com.cencat.user.vo.UserListVO;
import com.cencat.user.vo.UserVO;
import com.cencat.user.vo.LoginVO;
import com.cencat.user.vo.TokenVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 * @author cencat
 * @since 2024-01-01
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "userPage", allEntries = true)
    public Long createUser(UserCreateDTO dto) throws BusinessException {
        log.info("开始创建用户: username={}, tenantId={}", dto.getUsername(), dto.getTenantId());
        
        // 参数校验
        if (dto == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户名是否已存在
        if (checkUsernameExists(dto.getUsername(), null, dto.getTenantId())) {
            throw new BusinessException(ErrorCode.USER_ALREADY_EXISTS);
        }
        
        // 检查邮箱是否已存在
        if (CencatStringUtils.isNotBlank(dto.getEmail()) && checkEmailExists(dto.getEmail(), null, dto.getTenantId())) {
            throw new BusinessException(ErrorCode.EMAIL_ALREADY_EXISTS);
        }
        
        // 检查手机号是否已存在
        if (CencatStringUtils.isNotBlank(dto.getPhone()) && checkPhoneExists(dto.getPhone(), null, dto.getTenantId())) {
            throw new BusinessException(ErrorCode.PHONE_ALREADY_EXISTS);
        }
        
        // 创建用户实体
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        
        // 密码加密
        user.setPassword(CryptoUtils.md5WithSalt(dto.getPassword(), "cencat_salt"));
        
        // 设置默认值
        user.setStatus(UserStatus.NORMAL);
        user.setLoginCount(0);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        user.setDeleted(0); // 0表示未删除
        
        // 保存用户
        int result = userMapper.insert(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("用户创建成功: userId={}, username={}", user.getId(), dto.getUsername());
        return user.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"userPage", "userDetail"}, allEntries = true)
    public Boolean updateUser(UserUpdateDTO dto) throws BusinessException {
        log.info("开始更新用户: userId={}, tenantId={}", dto.getId(), dto.getTenantId());
        
        // 参数校验
        if (dto == null || dto.getId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户是否存在
        User existUser = userMapper.selectById(dto.getId());
        if (existUser == null || existUser.getDeleted() != 0 || !existUser.getTenantId().equals(dto.getTenantId())) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 检查邮箱是否已被其他用户使用
        if (CencatStringUtils.isNotBlank(dto.getEmail()) && checkEmailExists(dto.getEmail(), dto.getId(), dto.getTenantId())) {
            throw new BusinessException(ErrorCode.EMAIL_ALREADY_EXISTS);
        }
        
        // 检查手机号是否已被其他用户使用
        if (CencatStringUtils.isNotBlank(dto.getPhone()) && checkPhoneExists(dto.getPhone(), dto.getId(), dto.getTenantId())) {
            throw new BusinessException(ErrorCode.PHONE_ALREADY_EXISTS);
        }
        
        // 更新用户信息
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setUpdateTime(LocalDateTime.now());
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("用户更新成功: userId={}", dto.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = {"userPage", "userDetail"}, allEntries = true)
    public Boolean deleteUser(Long userId, Long tenantId) throws BusinessException {
        log.info("开始删除用户: userId={}, tenantId={}", userId, tenantId);
        
        // 参数校验
        if (userId == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户是否存在
        User existUser = userMapper.selectById(userId);
        if (existUser == null || existUser.getDeleted() != 0 || !existUser.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 逻辑删除
        User user = new User();
        user.setId(userId);
        user.setDeleted(1); // 1表示已删除
        user.setUpdateTime(LocalDateTime.now());
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("用户删除成功: userId={}", userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteUsers(List<Long> userIds, Long tenantId) throws BusinessException {
        log.info("开始批量删除用户: userIds={}, tenantId={}", userIds, tenantId);
        
        // 参数校验
        if (CollectionUtils.isEmpty(userIds) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 批量逻辑删除
        int result = userMapper.batchUpdateDeleted(userIds, tenantId, 1L); // 系统操作
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("批量删除用户成功: count={}", result);
        return true;
    }

    @Override
    public UserVO getUserById(Long userId, Long tenantId) throws BusinessException {
        log.info("查询用户详情: userId={}, tenantId={}", userId, tenantId);
        
        // 参数校验
        if (userId == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 查询用户
        User user = userMapper.selectById(userId);
        if (user == null || user.getDeleted() != 0 || !user.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 转换为VO
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        
        return userVO;
    }

    @Override
    public User getUserByUsername(String username, Long tenantId) throws BusinessException {
        log.info("根据用户名查询用户: username={}, tenantId={}", username, tenantId);
        
        // 参数校验
        if (CencatStringUtils.isBlank(username) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        return userMapper.selectByUsername(username, tenantId);
    }

    @Override
    public User getUserByEmail(String email, Long tenantId) throws BusinessException {
        log.info("根据邮箱查询用户: email={}, tenantId={}", email, tenantId);
        
        // 参数校验
        if (CencatStringUtils.isBlank(email) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        return userMapper.selectByEmail(email, tenantId);
    }

    @Override
    public User getUserByPhone(String phone, Long tenantId) throws BusinessException {
        log.info("根据手机号查询用户: phone={}, tenantId={}", phone, tenantId);
        
        // 参数校验
        if (CencatStringUtils.isBlank(phone) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        return userMapper.selectByPhone(phone, tenantId);
    }

    @Override
    @Cacheable(value = "userPage", 
               key = "T(com.cencat.user.config.CacheConfig.CacheKeyGenerator).generateUserPageKey(#queryDTO.tenantId, #queryDTO.pageNum, #queryDTO.pageSize, #queryDTO.username, #queryDTO.status)",
               condition = "#queryDTO != null and #queryDTO.tenantId != null")
    public IPage<UserListVO> getUserPage(UserQueryDTO queryDTO) throws BusinessException {
        log.info("分页查询用户列表: page={}, size={}, tenantId={}", queryDTO.getPageNum(), queryDTO.getPageSize(), queryDTO.getTenantId());
        
        // 参数校验
        if (queryDTO == null || queryDTO.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 构建分页查询
        PaginationHelper.PageQuery pageQuery = new PaginationHelper.PageQuery();
        pageQuery.setCurrent(queryDTO.getPageNum().longValue());
        pageQuery.setSize(queryDTO.getPageSize().longValue());
        
        // 构建查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (queryDTO.getTenantId() != null) {
            queryWrapper.eq("tenant_id", queryDTO.getTenantId());
        }
        if (StringUtils.hasText(queryDTO.getUsername())) {
            queryWrapper.like("username", queryDTO.getUsername());
        }
        if (StringUtils.hasText(queryDTO.getEmail())) {
            queryWrapper.like("email", queryDTO.getEmail());
        }
        if (StringUtils.hasText(queryDTO.getPhone())) {
            queryWrapper.like("phone", queryDTO.getPhone());
        }
        if (queryDTO.getStatus() != null) {
            queryWrapper.eq("status", queryDTO.getStatus());
        }
        queryWrapper.eq("deleted", false);
        
        // 执行分页查询并转换为VO
        PageResponse<UserListVO> pageResponse = PaginationHelper.executePage(userMapper, pageQuery, queryWrapper, this::convertToListVO);
        
        // 转换为IPage格式
        Page<UserListVO> page = new Page<>(pageResponse.getCurrent(), pageResponse.getSize(), pageResponse.getTotal());
        page.setRecords(pageResponse.getRecords());
        return page;
    }

    @Override
    public List<UserListVO> getUserList(UserQueryDTO queryDTO) throws BusinessException {
        log.info("查询用户列表: tenantId={}", queryDTO.getTenantId());
        
        // 参数校验
        if (queryDTO == null || queryDTO.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 查询用户列表（直接返回UserListVO类型）
        return userMapper.selectUserList(queryDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean enableUser(Long userId, Long tenantId, Long operatorId) throws BusinessException {
        return updateUserStatus(userId, UserStatus.NORMAL, tenantId, operatorId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean disableUser(Long userId, Long tenantId, Long operatorId) throws BusinessException {
        return updateUserStatus(userId, UserStatus.DISABLED, tenantId, operatorId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchUpdateUserStatus(List<Long> userIds, UserStatus status, Long tenantId, Long operatorId) throws BusinessException {
        log.info("批量更新用户状态: userIds={}, status={}, tenantId={}, operatorId={}", userIds, status, tenantId, operatorId);
        
        // 参数校验
        if (CollectionUtils.isEmpty(userIds) || status == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 批量更新状态
        int result = userMapper.batchUpdateStatus(userIds, status, tenantId, operatorId);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("批量更新用户状态成功: count={}", result);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean resetPassword(Long userId, String newPassword, Long tenantId, Long operatorId) throws BusinessException {
        log.info("重置用户密码: userId={}, tenantId={}, operatorId={}", userId, tenantId, operatorId);
        
        // 参数校验
        if (userId == null || CencatStringUtils.isBlank(newPassword) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户是否存在
        User existUser = userMapper.selectById(userId);
        if (existUser == null || existUser.getDeleted() != 0 || !existUser.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 更新密码
        User user = new User();
        user.setId(userId);
        user.setPassword(CryptoUtils.md5WithSalt(newPassword, "cencat_salt"));
        user.setUpdateTime(LocalDateTime.now());
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("重置密码成功: userId={}", userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changePassword(Long userId, String oldPassword, String newPassword, Long tenantId) throws BusinessException {
        log.info("修改用户密码: userId={}, tenantId={}", userId, tenantId);
        
        // 参数校验
        if (userId == null || CencatStringUtils.isBlank(oldPassword) || CencatStringUtils.isBlank(newPassword) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户是否存在
        User existUser = userMapper.selectById(userId);
        if (existUser == null || existUser.getDeleted() != 0 || !existUser.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 验证旧密码
        if (!CryptoUtils.matches(oldPassword, existUser.getPassword())) {
            throw new BusinessException(ErrorCode.OLD_PASSWORD_ERROR);
        }
        
        // 更新密码
        User user = new User();
        user.setId(userId);
        user.setPassword(CryptoUtils.md5WithSalt(newPassword, "cencat_salt"));
        user.setUpdateTime(LocalDateTime.now());
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("修改密码成功: userId={}", userId);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LoginVO login(LoginDTO dto) throws BusinessException {
        log.info("用户登录: username={}, loginIp={}, tenantId={}", dto.getUsername(), dto.getLoginIp(), dto.getTenantId());
        
        // 参数校验
        if (dto == null || CencatStringUtils.isBlank(dto.getUsername()) || 
            CencatStringUtils.isBlank(dto.getPassword()) || dto.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 查询用户
        User user = getUserByUsername(dto.getUsername(), dto.getTenantId());
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 检查用户状态
        if (!UserStatus.NORMAL.equals(user.getStatus())) {
            throw new BusinessException(ErrorCode.USER_STATUS_ERROR);
        }
        
        // 验证密码
        if (!CryptoUtils.matches(dto.getPassword(), user.getPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }
        
        // 更新登录信息
        updateLastLoginInfo(user.getId(), dto.getLoginIp(), dto.getTenantId());
        
        // 生成访问令牌和刷新令牌
        String accessToken = generateAccessToken(user.getId(), dto.getTenantId());
        String refreshToken = generateRefreshToken(user.getId(), dto.getTenantId());
        
        // 构建登录响应
        LoginVO loginVO = new LoginVO();
        loginVO.setUserId(user.getId());
        loginVO.setUsername(user.getUsername());
        loginVO.setNickname(user.getNickname());
        loginVO.setEmail(user.getEmail());
        loginVO.setPhone(user.getPhone());
        loginVO.setAccessToken(accessToken);
        loginVO.setRefreshToken(refreshToken);
        loginVO.setExpiresIn(7200L); // 2小时
        loginVO.setTokenType("Bearer");
        loginVO.setTenantId(dto.getTenantId());
        loginVO.setLoginTime(LocalDateTime.now());
        
        log.info("用户登录成功: userId={}, username={}", user.getId(), dto.getUsername());
        return loginVO;
    }

    @Override
    public Boolean logout(LogoutDTO dto) throws BusinessException {
        log.info("用户登出: userId={}, tenantId={}", dto.getUserId(), dto.getTenantId());
        
        // 参数校验
        if (dto == null || dto.getUserId() == null || dto.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 验证用户存在性
        UserVO user = getUserById(dto.getUserId(), dto.getTenantId());
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 清除访问令牌和刷新令牌（这里可以添加Redis缓存清除逻辑）
        if (CencatStringUtils.isNotBlank(dto.getAccessToken())) {
            // TODO: 清除Redis中的访问令牌
            log.info("清除访问令牌: userId={}", dto.getUserId());
        }
        
        if (CencatStringUtils.isNotBlank(dto.getRefreshToken())) {
            // TODO: 清除Redis中的刷新令牌
            log.info("清除刷新令牌: userId={}", dto.getUserId());
        }
        
        log.info("用户登出成功: userId={}, reason={}", dto.getUserId(), dto.getLogoutReason());
        return true;
    }

    @Override
    public TokenVO refreshToken(TokenDTO dto) throws BusinessException {
        log.info("刷新令牌: clientId={}, grantType={}, tenantId={}", dto.getClientId(), dto.getGrantType(), dto.getTenantId());
        
        // 参数校验
        if (dto == null || CencatStringUtils.isBlank(dto.getRefreshToken()) || dto.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 验证刷新令牌（这里可以添加Redis验证逻辑）
        if (!validateRefreshToken(dto.getRefreshToken(), dto.getTenantId())) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID);
        }
        
        // 从刷新令牌中解析用户ID（简化实现，实际应该从令牌中解析）
        Long userId = parseUserIdFromToken(dto.getRefreshToken());
        if (userId == null) {
            throw new BusinessException(ErrorCode.TOKEN_INVALID);
        }
        
        // 生成新的访问令牌和刷新令牌
        String newAccessToken = generateAccessToken(userId, dto.getTenantId());
        String newRefreshToken = generateRefreshToken(userId, dto.getTenantId());
        
        // 构建令牌响应
        TokenVO tokenVO = new TokenVO();
        tokenVO.setAccessToken(newAccessToken);
        tokenVO.setRefreshToken(newRefreshToken);
        tokenVO.setExpiresIn(7200L); // 2小时
        tokenVO.setTokenType("Bearer");
        tokenVO.setScope("read write");
        tokenVO.setTenantId(dto.getTenantId());
        tokenVO.setIssuedAt(LocalDateTime.now());
        
        log.info("令牌刷新成功: userId={}, clientId={}", userId, dto.getClientId());
        return tokenVO;
    }

    @Override
    public Boolean validateToken(String accessToken, Long tenantId) throws BusinessException {
        log.info("验证令牌: tenantId={}", tenantId);
        
        // 参数校验
        if (CencatStringUtils.isBlank(accessToken) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 验证访问令牌（这里可以添加Redis验证逻辑）
        boolean isValid = validateAccessToken(accessToken, tenantId);
        
        log.info("令牌验证结果: tenantId={}, isValid={}", tenantId, isValid);
        return isValid;
    }

    @Override
    @Deprecated
    @Transactional(rollbackFor = Exception.class)
    public UserVO loginLegacy(String username, String password, String loginIp, Long tenantId) throws BusinessException {
        log.info("用户登录(旧版本): username={}, loginIp={}, tenantId={}", username, loginIp, tenantId);
        
        // 参数校验
        if (CencatStringUtils.isBlank(username) || CencatStringUtils.isBlank(password) || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 查询用户
        User user = getUserByUsername(username, tenantId);
        if (user == null) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 检查用户状态
        if (!UserStatus.NORMAL.equals(user.getStatus())) {
            throw new BusinessException(ErrorCode.USER_STATUS_ERROR);
        }
        
        // 验证密码
        if (!CryptoUtils.matches(password, user.getPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }
        
        // 更新登录信息
        updateLastLoginInfo(user.getId(), loginIp, tenantId);
        
        // 转换为VO
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        // UserVO不包含密码字段，无需设置
        
        log.info("用户登录成功(旧版本): userId={}, username={}", user.getId(), username);
        return userVO;
    }

    @Override
    @Deprecated
    public Boolean logoutLegacy(Long userId, Long tenantId) throws BusinessException {
        log.info("用户登出(旧版本): userId={}, tenantId={}", userId, tenantId);
        
        // 参数校验
        if (userId == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 这里可以添加登出逻辑，如清除缓存、记录登出日志等
        
        log.info("用户登出成功(旧版本): userId={}", userId);
        return true;
    }

    /**
     * 生成访问令牌
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 访问令牌
     */
    private String generateAccessToken(Long userId, Long tenantId) {
        // 简化实现，实际应该使用JWT或其他安全令牌机制
        String tokenPrefix = "access_token_";
        String tokenSuffix = UUID.randomUUID().toString().replace("-", "");
        String accessToken = tokenPrefix + userId + "_" + tenantId + "_" + tokenSuffix;
        
        // TODO: 将令牌存储到Redis中，设置过期时间
        // redisTemplate.opsForValue().set("access_token:" + accessToken, userId + ":" + tenantId, 2, TimeUnit.HOURS);
        
        return accessToken;
    }

    /**
     * 生成刷新令牌
     * @param userId 用户ID
     * @param tenantId 租户ID
     * @return 刷新令牌
     */
    private String generateRefreshToken(Long userId, Long tenantId) {
        // 简化实现，实际应该使用JWT或其他安全令牌机制
        String tokenPrefix = "refresh_token_";
        String tokenSuffix = UUID.randomUUID().toString().replace("-", "");
        String refreshToken = tokenPrefix + userId + "_" + tenantId + "_" + tokenSuffix;
        
        // TODO: 将令牌存储到Redis中，设置过期时间（通常比访问令牌长）
        // redisTemplate.opsForValue().set("refresh_token:" + refreshToken, userId + ":" + tenantId, 7, TimeUnit.DAYS);
        
        return refreshToken;
    }

    /**
     * 验证访问令牌
     * @param accessToken 访问令牌
     * @param tenantId 租户ID
     * @return 是否有效
     */
    private boolean validateAccessToken(String accessToken, Long tenantId) {
        // 简化实现，实际应该从Redis或JWT中验证
        if (CencatStringUtils.isBlank(accessToken)) {
            return false;
        }
        
        // 检查令牌格式
        if (!accessToken.startsWith("access_token_")) {
            return false;
        }
        
        // TODO: 从Redis中验证令牌是否存在且未过期
        // String tokenKey = "access_token:" + accessToken;
        // String tokenValue = (String) redisTemplate.opsForValue().get(tokenKey);
        // return CencatStringUtils.isNotBlank(tokenValue);
        
        // 临时实现：简单格式验证
        String[] parts = accessToken.split("_");
        return parts.length >= 4;
    }

    /**
     * 验证刷新令牌
     * @param refreshToken 刷新令牌
     * @param tenantId 租户ID
     * @return 是否有效
     */
    private boolean validateRefreshToken(String refreshToken, Long tenantId) {
        // 简化实现，实际应该从Redis或JWT中验证
        if (CencatStringUtils.isBlank(refreshToken)) {
            return false;
        }
        
        // 检查令牌格式
        if (!refreshToken.startsWith("refresh_token_")) {
            return false;
        }
        
        // TODO: 从Redis中验证令牌是否存在且未过期
        // String tokenKey = "refresh_token:" + refreshToken;
        // String tokenValue = (String) redisTemplate.opsForValue().get(tokenKey);
        // return CencatStringUtils.isNotBlank(tokenValue);
        
        // 临时实现：简单格式验证
        String[] parts = refreshToken.split("_");
        return parts.length >= 4;
    }

    /**
     * 从令牌中解析用户ID
     * @param token 令牌
     * @return 用户ID
     */
    private Long parseUserIdFromToken(String token) {
        // 简化实现，实际应该从JWT中解析或从Redis中获取
        if (CencatStringUtils.isBlank(token)) {
            return null;
        }
        
        try {
            String[] parts = token.split("_");
            if (parts.length >= 4) {
                return Long.parseLong(parts[2]); // 用户ID在第3个位置
            }
        } catch (NumberFormatException e) {
            log.error("解析令牌中的用户ID失败: token={}, error={}", token, e.getMessage());
        }
        
        return null;
    }

    @Override
    public Long countUsers(UserQueryDTO queryDTO) throws BusinessException {
        log.info("统计用户数量: tenantId={}", queryDTO.getTenantId());
        
        // 参数校验
        if (queryDTO == null || queryDTO.getTenantId() == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        return userMapper.countUsers(queryDTO);
    }

    @Override
    public Boolean checkUsernameExists(String username, Long excludeUserId, Long tenantId) throws BusinessException {
        // 参数校验
        if (CencatStringUtils.isBlank(username) || tenantId == null) {
            return false;
        }
        
        // 使用专门的检查方法
        Long excludeId = excludeUserId != null ? excludeUserId : 0L;
        int count = userMapper.checkUsernameExists(username, excludeId, tenantId);
        return count > 0;
    }

    @Override
    public Boolean checkEmailExists(String email, Long excludeUserId, Long tenantId) throws BusinessException {
        // 参数校验
        if (CencatStringUtils.isBlank(email) || tenantId == null) {
            return false;
        }
        
        // 使用专门的检查方法
        Long excludeId = excludeUserId != null ? excludeUserId : 0L;
        int count = userMapper.checkEmailExists(email, excludeId, tenantId);
        return count > 0;
    }

    @Override
    public Boolean checkPhoneExists(String phone, Long excludeUserId, Long tenantId) throws BusinessException {
        // 参数校验
        if (CencatStringUtils.isBlank(phone) || tenantId == null) {
            return false;
        }
        
        // 使用专门的检查方法
        Long excludeId = excludeUserId != null ? excludeUserId : 0L;
        int count = userMapper.checkPhoneExists(phone, excludeId, tenantId);
        return count > 0;
    }

    @Override
    public List<User> getUsersByTenantId(Long tenantId) throws BusinessException {
        log.info("根据租户ID查询用户列表: tenantId={}", tenantId);
        
        // 参数校验
        if (tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        return userMapper.selectUsersByTenantId(tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateLastLoginInfo(Long userId, String loginIp, Long tenantId) throws BusinessException {
        log.info("更新最后登录信息: userId={}, loginIp={}, tenantId={}", userId, loginIp, tenantId);
        
        // 参数校验
        if (userId == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 更新登录信息
        User user = new User();
        user.setId(userId);
        user.setLastLoginIp(loginIp);
        user.setLastLoginTime(LocalDateTime.now());
        user.setLoginCount(userMapper.selectById(userId).getLoginCount() + 1);
        user.setUpdateTime(LocalDateTime.now());
        
        int result = userMapper.updateById(user);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        return true;
    }

    /**
     * 更新用户状态
     * @param userId 用户ID
     * @param status 状态
     * @param tenantId 租户ID
     * @param operatorId 操作人ID
     * @return 是否成功
     */
    private Boolean updateUserStatus(Long userId, UserStatus status, Long tenantId, Long operatorId) {
        log.info("更新用户状态: userId={}, status={}, tenantId={}, operatorId={}", userId, status, tenantId, operatorId);
        
        // 参数校验
        if (userId == null || status == null || tenantId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR);
        }
        
        // 检查用户是否存在
        User existUser = userMapper.selectById(userId);
        if (existUser == null || existUser.getDeleted() != 0 || !existUser.getTenantId().equals(tenantId)) {
            throw new BusinessException(ErrorCode.USER_NOT_EXISTS);
        }
        
        // 更新状态
        int result = userMapper.updateUserStatus(userId, status, tenantId, operatorId);
        if (result <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_FAILED);
        }
        
        log.info("更新用户状态成功: userId={}, status={}", userId, status);
        return true;
    }
    
    /**
     * 将User实体转换为UserListVO
     * @param user User实体
     * @return UserListVO
     */
    private UserListVO convertToListVO(User user) {
        UserListVO vo = new UserListVO();
        vo.setId(user.getId());
        vo.setUsername(user.getUsername());
        vo.setEmail(user.getEmail());
        vo.setPhone(user.getPhone());
        vo.setRealName(user.getRealName());
        vo.setAvatar(user.getAvatar());
        vo.setStatus(user.getStatus().name());
        vo.setLastLoginTime(user.getLastLoginTime());
        vo.setCreateTime(user.getCreateTime());
        vo.setUpdateTime(user.getUpdateTime());
        vo.setTenantId(user.getTenantId());
        vo.setGender(user.getGender() != null ? user.getGender().getCode() : null);
        vo.setLoginCount(user.getLoginCount());
        return vo;
    }
}